'use client';

import React, { useRef, useEffect, useState, useContext } from 'react';
import { createPortal } from 'react-dom';
import * as maptilersdk from '@maptiler/sdk';
import '@maptiler/sdk/dist/maptiler-sdk.css';
import { getCommunities, getHistoricalFlow, getODPairs } from '@/services/api';
import { TimeContext } from '@/context/TimeContext';
import { DataContext } from '@/context/DataContext';
import { mapDivergingByZero } from '@/lib/colorUtils';
import { MapControlContainer } from '@/lib/mapControlUtils';
import CommunityPanel from '@/app/components/CommunityPanel';
import LayerControlPanel from '@/app/components/LayerControlPanel';
import WeatherWidget from '@/app/components/WeatherWidget';

const CUMULATIVE_START_TIME = new Date('2021-05-01T00:00:00Z');

export default function Map() {
  const mapContainer = useRef<HTMLDivElement>(null);
  const map = useRef<maptilersdk.Map | null>(null);
  const [lng] = useState(114.0579);
  const [lat] = useState(22.5431);
  const [zoom] = useState(11);
  
  const [selected, setSelected] = useState<{ id: number; name?: string } | null>(null);
  
  // Portal 容器：右侧社区面板
  const [panelPortalContainer, setPanelPortalContainer] = useState<HTMLElement | null>(null);
  const panelControlRef = useRef<MapControlContainer | null>(null);

  // Portal 容器：左侧图层控制
  const [layerControlPortalContainer, setLayerControlPortalContainer] = useState<HTMLElement | null>(null);
  const layerControlRef = useRef<MapControlContainer | null>(null);

  // Portal 容器：右下角天气组件
  const [weatherPortalContainer, setWeatherPortalContainer] = useState<HTMLElement | null>(null);
  const weatherControlRef = useRef<MapControlContainer | null>(null);

  // 图层开关状态
  const [showHistoricalFlow, setShowHistoricalFlow] = useState(false);
  const [showODFlow, setShowODFlow] = useState(false);

  // 用于存储社区中心点坐标的映射（用于绘制 OD 弧线）
  const communityCoordinates = useRef<Record<number, [number, number]>>({});

  const timeContext = useContext(TimeContext);
  const dataContext = useContext(DataContext);

  // 1. 初始化地图
  useEffect(() => {
    if (map.current || !mapContainer.current) return;

    // maptilersdk.config.apiKey = process.env.NEXT_PUBLIC_MAPTILER_KEY!;
    const mapTilerKey = process.env.NEXT_PUBLIC_MAPTILER_KEY;
    if (!mapTilerKey) {
      console.error("MapTiler API key is not configured!");
      return;
    }
    map.current = new maptilersdk.Map({
      container: mapContainer.current,
      // style: "a75a6336-c1ba-4641-b043-363f963835a4",
      style: `https://api.maptiler.com/maps/dataviz-dark/style.json?key=${mapTilerKey}`,
      center: [lng, lat],
      zoom: zoom,
    });

    map.current.on('load', async () => {
      const communitiesData = await getCommunities();
      if (communitiesData.length === 0) return;

      const features = communitiesData.map((c: any) => {
        const isFeature = c.type === 'Feature' && c.geometry;
        const geometry = isFeature ? c.geometry : c.geometry;
        const propsFromApi = isFeature ? (c.properties || {}) : { name: c.name, district: c.district };
        const idFromApi = (isFeature ? c.properties?.id : c.id) ?? c.community_id;
        const cid = Number(idFromApi);

        // 计算社区中心点（简单取 bbox 中心）
        if (geometry.type === 'Polygon') {
          const coords = geometry.coordinates[0];
          const lngs = coords.map((p: number[]) => p[0]);
          const lats = coords.map((p: number[]) => p[1]);
          const centerLng = (Math.min(...lngs) + Math.max(...lngs)) / 2;
          const centerLat = (Math.min(...lats) + Math.max(...lats)) / 2;
          communityCoordinates.current[cid] = [centerLng, centerLat];
        }

        return {
          type: 'Feature',
          geometry,
          properties: {
            ...propsFromApi,
            id: cid,
            remaining_bikes: 0,
          },
        } as GeoJSON.Feature;
      });

      const geojsonSource: GeoJSON.FeatureCollection = {
        type: 'FeatureCollection',
        features,
      };

      map.current!.addSource('communities-source', { type: 'geojson', data: geojsonSource });
      map.current!.addLayer({
        id: 'communities-fill',
        type: 'fill',
        source: 'communities-source',
        paint: {
          'fill-color': '#007cbf',
          'fill-opacity': 0.6,
        },
      });
      map.current!.addLayer({
        id: 'communities-outline',
        type: 'line',
        source: 'communities-source',
        paint: { 'line-color': '#FFFFFF', 'line-width': 1 },
      });

      // 添加社区名称标签图层
      map.current!.addLayer({
        id: 'communities-labels',
        type: 'symbol',
        source: 'communities-source',
        layout: {
          // 从 feature 的 'name' 属性获取文本内容
          'text-field': ['get', 'name'],
          // 设置字体大小
          'text-size': 10,
          // 允许文本换行，以适应较长的社区名称
          'text-variable-anchor': ['top', 'bottom', 'left', 'right'],
          'text-radial-offset': 0.5,
          'text-justify': 'auto',
          // 避免标签相互重叠
          'text-allow-overlap': false,
        },
        paint: {
          // 设置文本颜色为白色
          'text-color': '#FFFFFF',
          // 添加黑色描边（光晕），让文字在任何背景下都清晰可见
          'text-halo-color': '#000000',
          'text-halo-width': 1,
          'text-halo-blur': 1,
        }
      });

      // 创建右侧社区详情面板的 Portal 容器
      const panelControl = new MapControlContainer('top-right');
      map.current!.addControl(panelControl, 'top-right');
      panelControlRef.current = panelControl;
      const panelCont = panelControl.getContainer();
      if (panelCont) setPanelPortalContainer(panelCont);

      // 创建左侧图层控制面板的 Portal 容器
      const layerControl = new MapControlContainer('top-left');
      map.current!.addControl(layerControl, 'top-left');
      layerControlRef.current = layerControl;
      const layerCont = layerControl.getContainer();
      if (layerCont) setLayerControlPortalContainer(layerCont);

      // 创建底部左侧天气控件容器
      const weatherControl = new MapControlContainer('bottom-left');
      map.current!.addControl(weatherControl, 'bottom-left');
      weatherControlRef.current = weatherControl;
      const weatherCont = weatherControl.getContainer();
      if (weatherCont) setWeatherPortalContainer(weatherCont);

      // 鼠标指针与点击事件
      map.current!.on('mouseenter', 'communities-fill', () => {
        map.current!.getCanvas().style.cursor = 'pointer';
      });
      map.current!.on('mouseleave', 'communities-fill', () => {
        map.current!.getCanvas().style.cursor = '';
      });
      map.current!.on('click', 'communities-fill', (e: any) => {
        const f = e.features?.[0];
        const idVal = Number(f?.properties?.id ?? f?.id);
        const nameVal = f?.properties?.name ?? `社区 ${idVal}`;
        if (Number.isFinite(idVal)) {
          setSelected({ id: idVal, name: nameVal });
        }
      });
    });

    return () => {
      if (map.current) {
        map.current.remove();
        map.current = null;
      }
    };
  }, [lng, lat, zoom]);

  // 2. 监听时间和数据变化，更新地图颜色（预测模式）
  useEffect(() => {
    if (!map.current || !map.current.isStyleLoaded() || !timeContext || !dataContext || dataContext.isLoading) {
      console.log("Map color update skipped: waiting for dependencies...");
      return;
    }

    // 如果"历史净流量"开关打开，跳过预测颜色更新（由下一个 effect 处理）
    if (showHistoricalFlow) return;

    const { currentTime } = timeContext;
    const { initialCounts, historicalFlows, predictedFlows } = dataContext;

    console.log(`Updating map colors (prediction mode) for time: ${currentTime.toISOString()}`);

    const remainingById: Record<number, number> = {};
    let maxPos = 0;
    let maxNegAbs = 0;

    for (let cid = 1; cid <= 74; cid++) {
      const initial = initialCounts[cid] ?? 0;
      let cumulativeFlow = 0;

      let currentSlot = new Date(CUMULATIVE_START_TIME);
      while (currentSlot < currentTime) {
        const slotStr = currentSlot.toISOString();
        cumulativeFlow += historicalFlows[cid]?.[slotStr] || 0;
        currentSlot.setMinutes(currentSlot.getMinutes() + 30);
      }

      const currentSlotStr = currentTime.toISOString();
      const predictedFlow = predictedFlows[cid]?.[currentSlotStr] || 0;

      const remainingBikes = initial + cumulativeFlow + predictedFlow;
      remainingById[cid] = remainingBikes;

      if (remainingBikes > maxPos) maxPos = remainingBikes;
      if (remainingBikes < 0 && Math.abs(remainingBikes) > maxNegAbs) maxNegAbs = Math.abs(remainingBikes);
    }

    const colorExpression: any[] = ['case'];
    const defaultColor = '#808080';
    const featureIdExpr: any = ['to-number', ['coalesce', ['get', 'id'], ['id']]];

    for (let cid = 1; cid <= 74; cid++) {
      const color = mapDivergingByZero(remainingById[cid], maxPos, maxNegAbs);
      colorExpression.push(['==', featureIdExpr, cid], color);
    }
    colorExpression.push(defaultColor);

    map.current.setPaintProperty('communities-fill', 'fill-color', colorExpression);
    console.log(`Map colors updated (prediction). maxPos=${maxPos}, maxNegAbs=${maxNegAbs}`);
  }, [timeContext?.currentTime, dataContext, showHistoricalFlow]);

  // 3. 监听"历史净流量"开关，切换颜色模式
  useEffect(() => {
    if (!map.current || !map.current.isStyleLoaded() || !timeContext) return;

    if (showHistoricalFlow) {
      const { currentTime } = timeContext;
      console.log(`Switching to historical flow mode for time: ${currentTime.toISOString()}`);

      const fetchAndApplyHistorical = async () => {
        const data = await getHistoricalFlow(currentTime.toISOString());
        if (!data) {
          console.error('Failed to fetch historical flow data');
          return;
        }

        const netFlowById: Record<number, number> = {};
        let maxPos = 0;
        let maxNegAbs = 0;

        for (const stat of data.stats) {
          netFlowById[stat.community_id] = stat.net_flow;
          if (stat.net_flow > maxPos) maxPos = stat.net_flow;
          if (stat.net_flow < 0 && Math.abs(stat.net_flow) > maxNegAbs) maxNegAbs = Math.abs(stat.net_flow);
        }

        const colorExpression: any[] = ['case'];
        const defaultColor = '#808080';
        const featureIdExpr: any = ['to-number', ['coalesce', ['get', 'id'], ['id']]];

        for (let cid = 1; cid <= 74; cid++) {
          const netFlow = netFlowById[cid] ?? 0;
          const color = mapDivergingByZero(netFlow, maxPos, maxNegAbs);
          colorExpression.push(['==', featureIdExpr, cid], color);
        }
        colorExpression.push(defaultColor);

        map.current!.setPaintProperty('communities-fill', 'fill-color', colorExpression);
        console.log(`Historical flow colors applied. maxPos=${maxPos}, maxNegAbs=${maxNegAbs}`);
      };

      fetchAndApplyHistorical();
    }
    // 当关闭时，会触发上一个 effect 恢复预测颜色
  }, [showHistoricalFlow, timeContext?.currentTime]);

  // 4. 监听"OD流量"开关，添加/移除弧线图层
  useEffect(() => {
    if (!map.current || !map.current.isStyleLoaded() || !timeContext) return;

    if (showODFlow) {
      const { currentTime } = timeContext;
      console.log(`Adding OD flow layer for time: ${currentTime.toISOString()}`);

      const fetchAndDrawOD = async () => {
        const data = await getODPairs(currentTime.toISOString());
        if (!data || data.od_pairs.length === 0) {
          console.warn('No OD pairs to display');
          return;
        }

        // 构建 GeoJSON LineString features
        const features: GeoJSON.Feature<GeoJSON.LineString>[] = data.od_pairs.map((pair) => {
          const start = communityCoordinates.current[pair.start_community_id];
          const end = communityCoordinates.current[pair.end_community_id];
          if (!start || !end) return null;

          return {
            type: 'Feature',
            geometry: {
              type: 'LineString',
              coordinates: [start, end],
            },
            properties: {
              flow_count: pair.flow_count,
            },
          };
        }).filter((f): f is GeoJSON.Feature<GeoJSON.LineString> => f !== null);

        const geojson: GeoJSON.FeatureCollection<GeoJSON.LineString> = {
          type: 'FeatureCollection',
          features,
        };

        // 如果图层已存在，先移除
        if (map.current!.getLayer('od-flow-layer')) {
          map.current!.removeLayer('od-flow-layer');
        }
        if (map.current!.getSource('od-flow-source')) {
          map.current!.removeSource('od-flow-source');
        }

        // 添加数据源
        map.current!.addSource('od-flow-source', {
          type: 'geojson',
          data: geojson,
        });

        // 计算线宽映射域
        const flows = data.od_pairs.map((p) => p.flow_count);
        const maxFlow = Math.max(...flows);
        const minFlow = Math.min(...flows);

        // 添加图层（使用表达式动态设置线宽）
        map.current!.addLayer({
          id: 'od-flow-layer',
          type: 'line',
          source: 'od-flow-source',
          layout: {
            'line-cap': 'round',
            'line-join': 'round',
          },
          paint: {
            'line-color': '#0cc2e2ff', // 统一青色
            'line-width': [
              'interpolate',
              ['linear'],
              ['get', 'flow_count'],
              minFlow, 1,
              maxFlow, 8,
            ],
            'line-opacity': 0.7,
          },
        });

        console.log(`OD flow layer added with ${features.length} arcs`);
      };

      fetchAndDrawOD();
    } else {
      // 关闭开关时移除图层
      if (map.current!.getLayer('od-flow-layer')) {
        map.current!.removeLayer('od-flow-layer');
      }
      if (map.current!.getSource('od-flow-source')) {
        map.current!.removeSource('od-flow-source');
      }
      console.log('OD flow layer removed');
    }
  }, [showODFlow, timeContext?.currentTime]);

  return (
    <>
      <div ref={mapContainer} className="w-full h-full" />
      
      {/* 右侧：社区详情面板 */}
      {panelPortalContainer && selected && createPortal(
        <CommunityPanel
          communityId={selected.id}
          communityName={selected.name}
          onClose={() => setSelected(null)}
        />,
        panelPortalContainer
      )}

      {/* 左侧：图层控制面板 */}
      {layerControlPortalContainer && createPortal(
        <LayerControlPanel
          showHistoricalFlow={showHistoricalFlow}
          showODFlow={showODFlow}
          onToggleHistorical={() => setShowHistoricalFlow(!showHistoricalFlow)}
          onToggleOD={() => setShowODFlow(!showODFlow)}
        />,
        layerControlPortalContainer
      )}
      {weatherPortalContainer && createPortal(<WeatherWidget />, weatherPortalContainer)}
    </>
  );
}